package org.luxor.commons.zookeeper.config;

import org.apache.curator.framework.recipes.cache.NodeCacheListener;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.luxor.commons.zookeeper.annotation.ZookeeperWatcher;
import org.luxor.commons.zookeeper.component.WatcherManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.StringUtils;

/**
 * 注册Zookeeper节点动态消息接收者
 *
 * @author Mr.Yan  @date: 2020/12/22
 */
public class ZookeeperListenerRegistrar implements BeanPostProcessor {
    private static final Logger logger = LoggerFactory.getLogger(ZookeeperListenerRegistrar.class);
    private WatcherManager watcherManager;

    public ZookeeperListenerRegistrar(WatcherManager watcherManager) {
        this.watcherManager = watcherManager;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        ZookeeperWatcher annotation = AnnotationUtils.findAnnotation(bean.getClass(), ZookeeperWatcher.class);
        if (annotation == null) {
            return bean;
        }
        String path = annotation.path();
        if (StringUtils.isEmpty(path)) {
            logger.warn("注册Watcher事件失败. Watcher对象:[ {} ]中,@ZookeeperWatcher未设置目标观察节点. -> [@ZookeeperWatcher(XXX))]", bean.getClass());
            return bean;
        }
        // 注册监听器
        switch (annotation.watcher()) {
            case NodeCache:
                registerNodeWatcher(path, bean);
                break;
            case PathChildrenCache:
                registerPathChildrenWatcher(path, bean);
                break;
            case TreeCache:
                registerTreeWatcher(path, bean);
                break;
            default:
                logger.warn("Watcher类型:[ {} ],不支持自动注册", annotation.watcher());
        }
        return bean;
    }


    private void registerNodeWatcher(String path, Object watcherListenerBean) {
        try {
            NodeCacheListener nodeCacheListener = (NodeCacheListener) watcherListenerBean;
            watcherManager.addNodeWatcher(path, nodeCacheListener);
        } catch (ClassCastException e) {
            logger.warn("注册NodeWatcher事件失败. Watcher对象:[ {} ],没实现准确的接口类. \n" +
                            " -> [public class {} implements NodeCacheListener { ... }]",
                    watcherListenerBean.getClass(), watcherListenerBean.getClass().getSimpleName());
            throw e;
        } catch (Exception e) {
            logger.warn("注册NodeWatcher事件失败.", e);
        }
    }


    private void registerPathChildrenWatcher(String path, Object watcherListenerBean) {
        try {
            PathChildrenCacheListener pathChildrenCacheListener = (PathChildrenCacheListener) watcherListenerBean;
            watcherManager.addPathChildrenWatcher(path, pathChildrenCacheListener);
        } catch (ClassCastException e) {
            logger.warn("注册PathChildrenWatcher事件失败. Watcher对象:[ {} ],没实现准确的接口类. \n" +
                            " -> [public class {} implements PathChildrenCacheListener { ... }]",
                    watcherListenerBean.getClass(), watcherListenerBean.getClass().getSimpleName());
            throw e;
        } catch (Exception e) {
            logger.warn("注册PathChildrenWatcher事件失败.", e);
        }
    }

    private void registerTreeWatcher(String path, Object watcherListenerBean) {
        try {
            TreeCacheListener treeCacheListener = (TreeCacheListener) watcherListenerBean;
            watcherManager.addTreeWatcher(path, treeCacheListener);
        } catch (ClassCastException e) {
            logger.warn("注册TreeWatcher事件失败. Watcher对象:[ {} ],没实现准确的接口类. \n" +
                            " -> [public class {} implements TreeCacheListener { ... }]",
                    watcherListenerBean.getClass(), watcherListenerBean.getClass().getSimpleName());
            throw e;
        } catch (Exception e) {
            logger.warn("注册TreeWatcher事件失败.", e);
        }
    }
}
